package controllers

import (
	"aflow/database"
	"aflow/models"
	"aflow/utils"
	"aflow/utils/sshTool"
	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/ssh"
	"log"
	"net/http"
	"os"
	"strconv"
)

func GetAllPipeline(c *gin.Context) {
	var pipeline []models.Pipeline
	if err := database.DB.Find(&pipeline).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, pipeline)
}

func GetPipeline(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
		return
	}
	var Pipeline models.Pipeline
	if err := database.DB.First(&Pipeline, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Pipeline not found"})
		return
	}
	c.JSON(http.StatusOK, Pipeline)

}

func CreatePipeline(c *gin.Context) {
	var pipeline models.Pipeline
	if err := c.ShouldBindJSON(&pipeline); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	if err := database.DB.Create(&pipeline).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusCreated, pipeline)
}

func UpdatePipeline(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
		return
	}
	var pipeline models.Pipeline
	if err := database.DB.First(&pipeline, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Pipeline not found"})
		return
	}

	if err := c.ShouldBindJSON(&pipeline); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if err := database.DB.Save(&pipeline).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, pipeline)
}

func DeletePipeline(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
		return
	}

	var Pipeline models.Pipeline
	if err := database.DB.First(&Pipeline, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Pipeline not found"})
		return
	}

	if err := database.DB.Delete(&Pipeline).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Pipeline deleted successfully"})
}

func ExecPipeline(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
		return
	}

	var Pipeline models.Pipeline
	if err := database.DB.First(&Pipeline, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Pipeline not found"})
		return
	}
	exec(c, Pipeline)
	c.JSON(http.StatusOK, gin.H{"message": "命令执行成功"})

}

func exec(c *gin.Context, pipeline models.Pipeline) {
	pool, exists := c.Get("sshPool")
	if !exists {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "SSH pool not initialized"})
		return
	}

	sessionPool := pool.(sshTool.ClientPool)

	var client = sshTool.GetSessionFormSessionPool(sessionPool, pipeline.Hostname)
	gitCommand := utils.GitCommandBuilder(pipeline)
	getSessionAndExecCommand(client, gitCommand)

	if pipeline.PipelineType == "maven" {
		mavenCommand := utils.MavenCommandBuilder(pipeline)
		getSessionAndExecCommand(client, mavenCommand)
	}

	if pipeline.PipelineType == "npm" {
		npmCommand := utils.NpmCommandBuilder(pipeline)
		getSessionAndExecCommand(client, npmCommand)
	}

	if pipeline.PipelineType == "go" {
		goCommand := utils.GolangCommandBuilder(pipeline)
		getSessionAndExecCommand(client, goCommand)
	}

	dockerCommand := utils.DockerCommandBuilder(pipeline)
	getSessionAndExecCommand(client, dockerCommand)
}

func getSessionAndExecCommand(client *ssh.Client, command string) {
	session, err := client.NewSession()
	if err != nil {
		log.Fatal("创建会话失败: ", err)
	}
	// 设置标准输入输出
	session.Stdout = os.Stdout
	session.Stderr = os.Stderr
	session.Stdin = os.Stdin
	err = session.Run(command)
	if err != nil {
	}
	defer func(session *ssh.Session) {
		err := session.Close()
		if err != nil {

		}
	}(session)
}
